package com.gitee.wsl.collections.map


import com.gitee.wsl.text.parameter.CaseInsensitiveMap


/**
 * Decorates a `Map` to ensure that the order of addition is retained
 * using a `List` to maintain order.
 *
 *
 * The order will be used via the iterators and toArray methods on the views.
 * The order is also returned by the `MapIterator`.
 * The `orderedMapIterator()` method accesses an iterator that can
 * iterate both forwards and backwards through the map.
 * In addition, non-interface methods are provided to access the map by index.
 *
 *
 *
 * If an object is added to the Map for a second time, it will remain in the
 * original position in the iteration.
 *
 *
 *
 * **Note that ListOrderedMap is not synchronized and is not thread-safe.**
 * If you wish to use this map from multiple threads concurrently, you must use
 * appropriate synchronization. The simplest approach is to wrap this map
 * using [java.util.Collections.synchronizedMap]. This class may throw
 * exceptions when accessed by concurrent threads without synchronization.
 *
 *
 *
 * **Note that ListOrderedMap doesn't work with
 * [IdentityHashMap][java.util.IdentityHashMap], [CaseInsensitiveMap],
 * or similar maps that violate the general contract of [java.util.Map].**
 * The `ListOrderedMap` (or, more precisely, the underlying `List`)
 * is relying on [equals()][Object.equals]. This is fine, as long as the
 * decorated `Map` is also based on [equals()][Object.equals],
 * and [hashCode()][Object.hashCode], which
 * [IdentityHashMap][java.util.IdentityHashMap], and
 * [CaseInsensitiveMap] don't: The former uses `==`, and
 * the latter uses [equals()][Object.equals] on a lower-cased
 * key.
 *
 *
 *
 * This class is [Serializable] starting with Commons Collections 3.1.
 *
 *
 * @param <K> the type of the keys in this map
 * @param <V> the type of the values in this map
 * @since 3.0
</V></K> */
//class ListOrderedMap<K, V>
//protected constructor(map: Map<K,V>) : DelegatingMap<K,V>(map), OrderedMap<K,V>{
//    internal class EntrySetView<K, V>(private val parent: ListOrderedMap<K,V>, private val insertOrder: List<K?>) :
//        AbstractMutableSet<Map.Entry<K,V>>() {
//        private var entrySet: Set<Map.Entry<K,V>>? = null
//            get() {
//                if (field == null) {
//                    field = parent.decorated().entries
//                }
//                return field
//            }
//
//        override val size: Int
//            get() = parent.size
//
//        public override fun clear() {
//            parent.clear()
//        }
//
//        public override fun contains(obj: Map.Entry<K,V>): Boolean {
//            return this.entrySet!!.contains(obj)
//        }
//
//        public override fun containsAll(coll: Collection<Map.Entry<K,V>>): Boolean {
//            return this.entrySet!!.containsAll(coll)
//        }
//
//        override fun equals(obj: Any?): Boolean {
//            if (obj === this) {
//                return true
//            }
//            return this.entrySet!! == obj
//        }
//
//        override fun hashCode(): Int {
//            return this.entrySet.hashCode()
//        }
//
//        public override fun isEmpty(): Boolean {
//            return parent.isEmpty()
//        }
//
//        public override fun iterator(): MutableIterator<Map.Entry<K,V>> {
//            return ListOrderedIterator(parent, insertOrder)
//        }
//
//        public override fun remove(obj: Map.Entry<K,V>): Boolean {
//            if (obj !is Map.Entry<*, *>) {
//                return false
//            }
//            if (this.entrySet!!.contains(obj)) {
//                val key = (obj as Map.Entry<K,V>).key
//                parent.remove(key)
//                return true
//            }
//            return false
//        }
//
////        public override fun size(): Int {
////            return parent.size()
////        }
//
//        override fun toString(): String {
//            return this.entrySet.toString()
//        }
//    }
//
//    fun decorated() = delegate
//    internal class KeySetView<K>(parent: ListOrderedMap<K?, *>?) : AbstractSet<K?>() {
//        private val parent: ListOrderedMap<K?, Any?>
//
//        init {
//            this.parent = parent as ListOrderedMap<K?, Any?>
//        }
//
//        public override fun clear() {
//            parent.clear()
//        }
//
//        public override fun contains(value: Any?): Boolean {
//            return parent.containsKey(value)
//        }
//
//        public override fun iterator(): Iterator<K?>? {
//            return object : AbstractUntypedIteratorDecorator<Map.Entry<K?, Any?>?, K?>(parent.entrySet()!!.iterator()) {
//                public override fun next(): K? {
//                    return getIterator().next().getKey()
//                }
//            }
//        }
//
//        public override fun size(): Int {
//            return parent.size()
//        }
//    }
//
//    internal class ListOrderedIterator<K, V>(
//        private val parent: ListOrderedMap<K,V>,
//        insertOrder: List<K>
//    ) : AbstractUntypedIteratorDecorator<K, Map.Entry<K,V>>(insertOrder.iterator()) {
//        private var last: K? = null
//
//        public override fun next(): Map.Entry<K,V>? {
//            last = getIterator().next()
//            return ListOrderedMapEntry<K,V>(parent, last)
//        }
//
//        public override fun remove() {
//            super.remove()
//            parent.decorated().remove(last)
//        }
//    }
//
//    internal class ListOrderedMapEntry<K, V>(private val parent: ListOrderedMap<K,V>, key: K?) :
//        AbstractMapEntry<K,V>(key, null) {
//        val value: V?
//            get() = parent.get(getKey())
//
//        public override fun setValue(value: V?): V? {
//            return parent.decorated().put(getKey(), value)
//        }
//    }
//
//    internal class ListOrderedMapIterator<K, V>(private val parent: ListOrderedMap<K,V>) :
//        OrderedMapIterator<K,V>, ResettableIterator<K?> {
//        private var iterator: ListIterator<K?>
//        private var last: K? = null
//        private var readable = false
//
//        init {
//            this.iterator = parent.insertOrder.listIterator()
//        }
//
//        override fun getKey(): K? {
//            if (!readable) {
//                throw java.lang.IllegalStateException(AbstractHashedMap.GETKEY_INVALID)
//            }
//            return last
//        }
//
//        override fun getValue(): V? {
//            if (!readable) {
//                throw java.lang.IllegalStateException(AbstractHashedMap.GETVALUE_INVALID)
//            }
//            return parent.get(last)
//        }
//
//        override fun hasNext(): Boolean {
//            return iterator.hasNext()
//        }
//
//        override fun hasPrevious(): Boolean {
//            return iterator.hasPrevious()
//        }
//
//        override fun next(): K? {
//            last = iterator.next()
//            readable = true
//            return last
//        }
//
//        override fun previous(): K? {
//            last = iterator.previous()
//            readable = true
//            return last
//        }
//
//        public override fun remove() {
//            if (!readable) {
//                throw java.lang.IllegalStateException(AbstractHashedMap.REMOVE_INVALID)
//            }
//            iterator.remove()
//            parent.map.remove(last)
//            readable = false
//        }
//
//        override fun reset() {
//            iterator = parent.insertOrder.listIterator()
//            last = null
//            readable = false
//        }
//
//        override fun setValue(value: V?): V? {
//            if (!readable) {
//                throw java.lang.IllegalStateException(AbstractHashedMap.SETVALUE_INVALID)
//            }
//            return parent.map.put(last, value)
//        }
//
//        override fun toString(): String {
//            if (readable) {
//                return "Iterator[" + getKey() + "=" + getValue() + "]"
//            }
//            return "Iterator[]"
//        }
//    }
//
//    internal class ValuesView<V>(private val parent: ListOrderedMap<*, V>) : AbstractMutableList<V>() {
//
//
//        public override fun clear() {
//            parent.clear()
//        }
//
//        public override fun contains(value: V): Boolean {
//            return parent.containsValue(value)
//        }
//
//        public override fun get(index: Int): V? {
//            return parent.getValue(index)
//        }
//
//        public override fun iterator(): Iterator<V> {
//            return object : AbstractUntypedIteratorDecorator<Map.Entry<Any?, V?>?, V?>(parent.entrySet()!!.iterator()) {
//                public override fun next(): V? {
//                    return getIterator().next().getValue()
//                }
//            }
//        }
//
//        public override fun remove(index: Int): V? {
//            return parent.remove(index)
//        }
//
//        public override fun set(index: Int, value: V?): V? {
//            return parent.setValue(index, value)
//        }
//
////        public override fun size(): Int {
////            return parent.size()
////        }
//    }
//
//    /** Internal list to hold the sequence of objects  */
//    private val insertOrder = ArrayList<>()
//
//    /**
//     * Constructs a new empty `ListOrderedMap` that decorates
//     * a `HashMap`.
//     *
//     * @since 3.1
//     */
//    constructor() : this(HashMap())
//
//    /**
//     * Constructor that wraps (not copies).
//     *
//     * @param map  the map to decorate, must not be null
//     * @throws NullPointerException if map is null
//     */
//    init {
//        insertOrder.addAll(decorated().keys)
//    }
//
//    /**
//     * Gets an unmodifiable List view of the keys which changes as the map changes.
//     *
//     *
//     * The returned list is unmodifiable because changes to the values of
//     * the list (using [java.util.ListIterator.set]) will
//     * effectively remove the value from the list and reinsert that value at
//     * the end of the list, which is an unexpected side effect of changing the
//     * value of a list.  This occurs because changing the key, changes when the
//     * mapping is added to the map and thus where it appears in the list.
//     *
//     *
//     *
//     * An alternative to this method is to use the better named
//     * [.keyList] or [.keySet].
//     *
//     *
//     * @see .keyList
//     * @see .keySet
//     * @return The ordered list of keys.
//     */
//    fun asList(): List<K> {
//        return keyList()
//    }
//
//    public override fun clear() {
//        decorated().clear()
//        insertOrder.clear()
//    }
//
//    /**
//     * Gets a view over the entries in the map.
//     *
//     *
//     * The Set will be ordered by object insertion into the map.
//     *
//     *
//     * @return the fully modifiable set view over the entries
//     */
//    public override fun entrySet(): Set<Map.Entry<K,V>?>? {
//        return ListOrderedMap.EntrySetView<K,V>(this, insertOrder)
//    }
//
//    /**
//     * Gets the first key in this map by insert order.
//     *
//     * @return the first key currently in this map
//     * @throws NoSuchElementException if this map is empty
//     */
//    override fun firstKey(): K? {
//        if (isEmpty()) {
//            throw NoSuchElementException("Map is empty")
//        }
//        return insertOrder.get(0)
//    }
//
//    /**
//     * Gets the key at the specified index.
//     *
//     * @param index  the index to retrieve
//     * @return the key at the specified index
//     * @throws IndexOutOfBoundsException if the index is invalid
//     */
//    fun get(index: Int): K? {
//        return insertOrder.get(index)
//    }
//
//    /**
//     * Gets the value at the specified index.
//     *
//     * @param index  the index to retrieve
//     * @return the key at the specified index
//     * @throws IndexOutOfBoundsException if the index is invalid
//     */
//    fun getValue(index: Int): V? {
//        return get(insertOrder.get(index))
//    }
//
//    /**
//     * Gets the index of the specified key.
//     *
//     * @param key  the key to find the index of
//     * @return the index, or -1 if not found
//     */
//    fun indexOf(key: Any?): Int {
//        return insertOrder.indexOf(key)
//    }
//
//    /**
//     * Gets a view over the keys in the map as a List.
//     *
//     *
//     * The List will be ordered by object insertion into the map.
//     * The List is unmodifiable.
//     *
//     *
//     * @see .keySet
//     * @return the unmodifiable list view over the keys
//     * @since 3.2
//     */
//    fun keyList(): List<K> {
//        return insertOrder
//    }
//
//    /**
//     * Gets a view over the keys in the map.
//     *
//     *
//     * The Collection will be ordered by object insertion into the map.
//     *
//     *
//     * @see .keyList
//     * @return the fully modifiable collection view over the keys
//     */
//    public override fun keySet(): Set<K?>? {
//        return ListOrderedMap.KeySetView<K?>(this)
//    }
//
//    /**
//     * Gets the last key in this map by insert order.
//     *
//     * @return the last key currently in this map
//     * @throws NoSuchElementException if this map is empty
//     */
//    override fun lastKey(): K? {
//        if (isEmpty()) {
//            throw NoSuchElementException("Map is empty")
//        }
//        return insertOrder.get(size() - 1)
//    }
//
//    override fun mapIterator(): OrderedMapIterator<K,V> {
//        return ListOrderedMap.ListOrderedMapIterator<K,V>(this)
//    }
//
//    /**
//     * Gets the next key to the one specified using insert order.
//     * This method performs a list search to find the key and is O(n).
//     *
//     * @param key  the key to find previous for
//     * @return the next key, null if no match or at start
//     */
//    override fun nextKey(key: Any?): K? {
//        val index = insertOrder.indexOf(key)
//        if (index >= 0 && index < size() - 1) {
//            return insertOrder.get(index + 1)
//        }
//        return null
//    }
//
//    /**
//     * Gets the previous key to the one specified using insert order.
//     * This method performs a list search to find the key and is O(n).
//     *
//     * @param key  the key to find previous for
//     * @return the previous key, null if no match or at start
//     */
//    override fun previousKey(key: Any?): K? {
//        val index = insertOrder.indexOf(key)
//        if (index > 0) {
//            return insertOrder.get(index - 1)
//        }
//        return null
//    }
//
//    /**
//     * Puts a key-value mapping into the map at the specified index.
//     *
//     *
//     * If the map already contains the key, then the original mapping
//     * is removed and the new mapping added at the specified index.
//     * The remove may change the effect of the index. The index is
//     * always calculated relative to the original state of the map.
//     *
//     *
//     *
//     * Thus, the steps are: (1) remove the existing key-value mapping,
//     * then (2) insert the new key-value mapping at the position it
//     * would have been inserted had the remove not occurred.
//     *
//     *
//     * @param index  the index at which the mapping should be inserted
//     * @param key  the key
//     * @param value  the value
//     * @return the value previously mapped to the key
//     * @throws IndexOutOfBoundsException if the index is out of range [0, size]
//     * @since 3.2
//     */
//    fun put(index: Int, key: K?, value: V?): V? {
//        var index = index
//        if (index < 0 || index > insertOrder.size()) {
//            throw java.lang.IndexOutOfBoundsException("Index: " + index + ", Size: " + insertOrder.size())
//        }
//
//        val m: Map<K,V> = decorated()
//        if (m.containsKey(key)) {
//            val result: V? = m.remove(key)
//            val pos = insertOrder.indexOf(key)
//            insertOrder.remove(pos)
//            if (pos < index) {
//                index--
//            }
//            insertOrder.add(index, key)
//            m.put(key, value)
//            return result
//        }
//        insertOrder.add(index, key)
//        m.put(key, value)
//        return null
//    }
//
//    public override fun put(key: K?, value: V?): V? {
//        if (decorated().containsKey(key)) {
//            // re-adding doesn't change order
//            return decorated().put(key, value)
//        }
//        // first add, so add to both map and list
//        val result: V? = decorated().put(key, value)
//        insertOrder.add(key)
//        return result
//    }
//
//    /**
//     * Puts the values contained in a supplied Map into the Map starting at
//     * the specified index.
//     *
//     * @param index the index in the Map to start at.
//     * @param map the Map containing the entries to be added.
//     * @throws IndexOutOfBoundsException if the index is out of range [0, size]
//     */
//    fun putAll(index: Int, map: Map<out K?, out V?>) {
//        var index = index
//        if (index < 0 || index > insertOrder.size()) {
//            throw java.lang.IndexOutOfBoundsException("Index: " + index + ", Size: " + insertOrder.size())
//        }
//        for (entry in map.entrySet()) {
//            val key: K? = entry.getKey()
//            val contains = containsKey(key)
//            // The return value of put is null if the key did not exist OR the value was null
//            // so it cannot be used to determine whether the key was added
//            put(index, entry.getKey(), entry.getValue())
//            if (!contains) {
//                // if no key was replaced, increment the index
//                index++
//            } else {
//                // otherwise put the next item after the currently inserted key
//                index = indexOf(entry.getKey()) + 1
//            }
//        }
//    }
//
//    public override fun putAll(map: Map<out K?, out V?>) {
//        for (entry in map.entrySet()) {
//            put(entry.getKey(), entry.getValue())
//        }
//    }
//
//    /**
//     * Deserializes the map in using a custom routine.
//     *
//     * @param in  the input stream
//     * @throws IOException if an error occurs while reading from the stream
//     * @throws ClassNotFoundException if an object read from the stream cannot be loaded
//     * @since 3.1
//     */
//    @Throws(
//        IOException::class,
//        java.lang.ClassNotFoundException::class
//    )  // (1) should only fail if input stream is incorrect
//    private fun readObject(`in`: ObjectInputStream) {
//        `in`.defaultReadObject()
//        map = `in`.readObject() as Map<K,V>? // (1)
//    }
//
//    /**
//     * Removes the element at the specified index.
//     *
//     * @param index  the index of the object to remove
//     * @return the removed value, or `null` if none existed
//     * @throws IndexOutOfBoundsException if the index is invalid
//     */
//    fun remove(index: Int): V? {
//        return remove(get(index))
//    }
//
//    public override fun remove(key: Any?): V? {
//        var result: V? = null
//        if (decorated().containsKey(key)) {
//            result = decorated().remove(key)
//            insertOrder.remove(key)
//        }
//        return result
//    }
//
//    /**
//     * Sets the value at the specified index.
//     *
//     * @param index  the index of the value to set
//     * @param value  the new value to set
//     * @return the previous value at that index
//     * @throws IndexOutOfBoundsException if the index is invalid
//     * @since 3.2
//     */
//    fun setValue(index: Int, value: V?): V? {
//        val key = insertOrder.get(index)
//        return put(key, value)
//    }
//
//    /**
//     * Returns the Map as a string.
//     *
//     * @return the Map as a String
//     */
//    override fun toString(): String {
//        if (isEmpty()) {
//            return "{}"
//        }
//        val buf: java.lang.StringBuilder = java.lang.StringBuilder()
//        buf.append('{')
//        var first = true
//        for (entry in entrySet()!!) {
//            val key: K? = entry.getKey()
//            val value: V? = entry.getValue()
//            if (first) {
//                first = false
//            } else {
//                buf.append(", ")
//            }
//            buf.append(if (key === this) "(this Map)" else key)
//            buf.append('=')
//            buf.append(if (value === this) "(this Map)" else value)
//        }
//        buf.append('}')
//        return buf.toString()
//    }
//
//    /**
//     * Gets a view over the values in the map as a List.
//     *
//     *
//     * The List will be ordered by object insertion into the map.
//     * The List supports remove and set, but does not support add.
//     *
//     *
//     * @see .values
//     * @return the partially modifiable list view over the values
//     * @since 3.2
//     */
//    fun valueList(): List<V?>? {
//        return ListOrderedMap.ValuesView<V?>(this)
//    }
//
//    /**
//     * Gets a view over the values in the map.
//     *
//     *
//     * The Collection will be ordered by object insertion into the map.
//     *
//     *
//     *
//     * From Commons Collections 3.2, this Collection can be cast
//     * to a list, see [.valueList]
//     *
//     *
//     * @see .valueList
//     * @return the fully modifiable collection view over the values
//     */
//    public override fun values(): Collection<V?>? {
//        return ListOrderedMap.ValuesView<V?>(this)
//    }
//
//    /**
//     * Serializes this object to an ObjectOutputStream.
//     *
//     * @param out the target ObjectOutputStream.
//     * @throws IOException thrown when an I/O errors occur writing to the target stream.
//     * @since 3.1
//     */
//    @Throws(IOException::class)
//    private fun writeObject(out: ObjectOutputStream) {
//        out.defaultWriteObject()
//        out.writeObject(map)
//    }
//
//    companion object {
//        /** Serialization version  */
//        private const val serialVersionUID = 2728177751851003750L
//
//        /**
//         * Factory method to create an ordered map.
//         *
//         *
//         * An `ArrayList` is used to retain order.
//         *
//         *
//         * @param <K>  the key type
//         * @param <V>  the value type
//         * @param map  the map to decorate, must not be null
//         * @return a new list ordered map
//         * @throws NullPointerException if map is null
//         * @since 4.0
//        </V></K> */
//        fun <K, V> listOrderedMap(map: Map<K,V>?): ListOrderedMap<K,V> {
//            return ListOrderedMap<K,V>(map)
//        }
//    }
//}
